package com.andy;

import com.andy.base.config.ServerConfig;
import com.andy.base.conn.Connector;
import com.andy.base.mapper.Context;
import com.andy.base.mapper.Engine;
import com.andy.base.mapper.Host;
import com.andy.base.mapper.Wrapper;
import com.andy.base.servlet.HttpServlet;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Bootstrap {

    private ServerConfig serverConfig = new ServerConfig();

    public void start() throws Exception{
        //加载配置文件
        loadServerConfig();

        //加载Engine
        Engine engine = loadEngine();

        //启动连接器，接受TCP连接
        Connector connector = new Connector(engine, serverConfig);
        connector.start();
    }

    /**
     * 加载Engine
     * @return
     */
    private Engine loadEngine(){
        //获取appBase地址
        String appBase = serverConfig.getAppBase();
        //获取地址下的所有子文件夹
        File appBaseFile = new File(appBase);
        File[] files = appBaseFile.listFiles();

        //封装context
        Map<String,Context> contextMap = new HashMap<>();
        for(File file:files){
            if(file.isDirectory()){
                //封装wrapper
                Map<String, Wrapper> wrapperMap = new HashMap<>();
                loadServlet(file,wrapperMap);
                //封装Context并放入map容器
                Context context = new Context(wrapperMap);
                contextMap.put(file.getName(),context);
            }
        }
        //封装到Host
        Host host = new Host(contextMap);
        //封装到Engine
        Engine engine = new Engine(host);

        return engine;
    }

    /**
     * 解析web.xml，初始化Servlet
     * @param context
     * @param wrapperMap
     */
    private void loadServlet(File context,Map<String, Wrapper> wrapperMap) {
        SAXReader saxReader = new SAXReader();
        try {
            //拿到context文件夹下的web.xml
            File webXml = new File(context.getPath()+"\\"+"web.xml");
            //解析web.xml
            InputStream resourceAsStream = new FileInputStream(webXml);
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();

            List<Element> selectNodes = rootElement.selectNodes("//servlet");
            for (int i = 0; i < selectNodes.size(); i++) {
                Element element =  selectNodes.get(i);
                // <servlet-name>lagou</servlet-name>
                Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletnameElement.getStringValue();
                // <servlet-class>server.LagouServlet</servlet-class>
                Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletclassElement.getStringValue();

                // 根据servlet-name的值找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                // /lagou
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();

                //路径+servlet路径
                String location = context.getAbsolutePath();
                String classPath = servletClass;
                //使用urlClassLoader加载class
                String fileUrl = "file:"+location+"/";
                fileUrl = fileUrl.replaceAll("/","\\\\");
                //加载class
                URLClassLoader loader = new URLClassLoader(new URL[] { new URL(fileUrl) });
                Class aClass = loader.loadClass(classPath);
                //实例化servlet
                HttpServlet servlet = (HttpServlet) aClass.newInstance();
                wrapperMap.put(urlPattern,new Wrapper(servlet));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 加载service配置文件
     */
    private void loadServerConfig(){
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("server.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();

            //加载端口的配置
            Element connector = (Element)rootElement.selectSingleNode("//Connector");
            String port = connector.attribute("port").getValue();
            serverConfig.setPort(port);
            //加载web app地址的配置
            Element host = (Element)rootElement.selectSingleNode("//Host");
            String appBase = host.attribute("appBase").getValue();
            serverConfig.setAppBase(appBase);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * main
     *
     * http://127.0.0.1:8080/MyWeb1/s1          自定义的servlet
     * http://127.0.0.1:8080/MyWeb1/index.html  自定义的静态文件
     * http://127.0.0.1:8080/MyWeb1/abcde       不存在的servlet
     * http://127.0.0.1:8080/MyWeb1/abcde.html  不存在的静态文件
     *
     * http://127.0.0.1:8080/MyWeb2/s2          应用2的servlet
     * http://127.0.0.1:8080/MyWeb2/index.html  应用2的静态文件
     *
     * @param args
     */
    public static void main(String[] args){
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
